/**
 * Copyright(c) 2010 Ceno Techonologies Co., Ltd.
 *
 * History:
 *   15-1-10 下午2:48 Created by lyyang
 */
package com.jade.bss.business.groupon.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.bss.base.BssException;
import com.jade.bss.business.groupon.*;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.util.PagingList;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;

/**
 * 团购券管理器
 *
 * @author <a href="mailto:lyyang@ceno.cn">lyyang</a>
 * @version 1.0 15-1-10 下午2:48
 */
@Named ("ags_grouponManager")
public class GrouponManagerImpl
        implements GrouponManager
{
    protected Log logger = LogFactory.getLog(this.getClass());
    private Map<String, Sniffer> sniffers;
    private SnifferSettingDao settingDao;
    private GrouponDao grouponDao;
    //嗅探间隔时间,单位毫秒,只有时间超过这个间隔,程序才会发起嗅探,否则返回数据库中的数据
    private long snifferInterval;

    public Map<String, Sniffer> getSniffers()
    {
        return sniffers;
    }

    public void setSniffers(Map<String, Sniffer> sniffers)
    {
        this.sniffers = sniffers;
    }

    public SnifferSettingDao getSettingDao()
    {
        return settingDao;
    }

    @Inject
    public void setSettingDao(@Named ("ags_snifferSettingDao") SnifferSettingDao settingDao)
    {
        this.settingDao = settingDao;
    }

    public GrouponDao getGrouponDao()
    {
        return grouponDao;
    }

    @Inject
    public void setGrouponDao(@Named ("ags_grouponDao") GrouponDao grouponDao)
    {
        this.grouponDao = grouponDao;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void addSetting(SnifferSetting setting)
    {
        settingDao.add(setting);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void updateSetting(SnifferSetting setting)
    {
        settingDao.update(setting);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeSetting(long... ids)
    {
        settingDao.remove(ids);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeSetting(String ownerId, String ownerType)
    {
        settingDao.remove(ownerId, ownerType);
    }

    public SnifferSetting getSetting(long id)
    {
        return settingDao.get(id);
    }

    public SnifferSetting getSetting(String ownerId, String ownerType, String channel)
    {
        return settingDao.get(ownerId, ownerType, channel);
    }

    public List<SnifferSetting> listSetting(String ownerId, String ownerType)
    {
        return settingDao.list(ownerId, ownerType);
    }

    public List<SnifferSetting> listSetting(Criteria criteria)
    {
        return settingDao.list(criteria);
    }

    public PagingList<SnifferSetting> querySetting(Criteria criteria)
    {
        return settingDao.query(criteria);
    }

    public long getSnifferInterval()
    {
        return snifferInterval;
    }

    public void setSnifferInterval(long snifferInterval)
    {
        this.snifferInterval = snifferInterval;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public List<Groupon> sniffer()
            throws BssException
    {
        List<Groupon> groupons = new ArrayList<Groupon>();
        List<SnifferSetting> settings = settingDao.list(new Criteria(-1, -1));
        if (settings == null || settings.size() == 0) {
            logger.warn("Can't find any sniffer settings ");
            return groupons;
        }
        for (SnifferSetting setting : settings) {
            groupons.addAll(sniffer(setting));

        }
        return groupons;
    }

    public Groupon get(long id)
    {
        return grouponDao.get(id);
    }

    private List<Groupon> sniffer(SnifferSetting setting)
            throws BssException
    {
        List<Groupon> groupons = new ArrayList<Groupon>();
        long current = System.currentTimeMillis();
        //判断上次sniffer的时间和当前时间的时间差,如果小于snifferInterval,则不需要sniffer
        if (setting.getLastUpdate() == null || current - setting.getLastUpdate().getTime() > snifferInterval) {
            groupons.addAll(
                    sniffer(setting.getOwnerId(), setting.getOwnerType(), setting.getCity(), setting.getChannel(),
                            setting.getKeyword()));
            setting.setLastUpdate(new Date());
            settingDao.update(setting);

        }
        else {
            logger.debug("sniffer don't have to run.(" + setting.getChannel() + "," + setting.getKeyword() + ")");
        }
        return groupons;

    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public List<Groupon> sniffer(String ownerId, String ownerType)
            throws BssException
    {
        List<Groupon> groupons = new ArrayList<Groupon>();
        //根据sniffer setting配置,获取这个商家所有的sniffer 的渠道(例如:大众点评,美团等等哦)
        List<SnifferSetting> settings = settingDao.list(ownerId, ownerType);
        if (settings == null || settings.size() == 0) {
            logger.warn("Can't find any sniffer settings (ownerId:" + ownerId + ",ownerType:" + ownerType + ")");
            return groupons;
        }
        for (SnifferSetting setting : settings) {
            groupons.addAll(sniffer(setting));

        }
        return groupons;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    private void removeGroupon(String ownerId, String ownerType, String channel)
    {
        Criteria criteria = new Criteria(-1, -1);
        criteria.add(Restrictions.eq("ownerId", ownerId));
        criteria.add(Restrictions.eq("ownerType", ownerType));
        criteria.add(Restrictions.eq("channel", channel));
        List<Groupon> groupons = grouponDao.list(criteria);
        if (groupons != null && groupons.size() > 0) {
            for (Groupon groupon : groupons) {
                grouponDao.remove(groupon);
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    private void addGroupon(Groupon groupon)
    {
        grouponDao.add(groupon);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public List<Groupon> sniffer(String ownerId, String ownerType, String city, String channel, String keyword)
            throws BssException
    {
        List<Groupon> groupons = new ArrayList<Groupon>();
        //根据setting的渠道获取相应的sniffer
        Sniffer sniffer = sniffers.get(channel);
        if (sniffer == null) {
            logger.warn(
                    "Can't find any sniffer (ownerId:" + ownerId + ",ownerType:" + ownerType + ",channel:" + channel +
                            ")");
            return groupons;
        }
        removeGroupon(ownerId, ownerType, channel);
        logger.debug(
                "start sniffer (ownerId:" + ownerId + ",ownerType:" + ownerType + ",channel:" + channel + ",keyword:" +
                        keyword + ")");
        List<Groupon> snifferGroupons = sniffer.find(ownerId, ownerType, city, keyword);
        if (snifferGroupons != null) {
            for (Groupon groupon : snifferGroupons) {
                addGroupon(groupon);
                groupons.add(groupon);
            }
        }
        return groupons;
    }

    public List<Groupon> listGroupon(String ownerId, String ownerType, Criteria criteria)
            throws BssException
    {
        if (criteria == null) {
            criteria = new Criteria(-1, -1);
        }

        if (!StringUtils.isEmpty(ownerId)) {
            criteria.add(Restrictions.eq("ownerId", ownerId));
        }
        if (!StringUtils.isEmpty(ownerType)) {
            criteria.add(Restrictions.eq("ownerType", ownerType));
        }
        return grouponDao.list(criteria);

    }

    public PagingList<Groupon> queryGroupon(String ownerId, String ownerType, Criteria criteria)
    {
        if (!StringUtils.isEmpty(ownerId)) {
            criteria.add(Restrictions.eq("ownerId", ownerId));
        }
        if (!StringUtils.isEmpty(ownerType)) {
            criteria.add(Restrictions.eq("ownerType", ownerType));
        }
        return grouponDao.query(criteria);
    }


}
